#!/usr/bin/env python

import gtk.keysyms
import webbrowser
import subprocess
import gettext
import os
import gobject
from blend.gui import decryptDialog
from blend.gui import encryptDialog
from blend.gui import colourSelectionDialog
from blend.gui import fileSelectionDialog
from blend.gui import emoteWindow
from blend.gui import selectContactDialog
import fileSelectionDialogSignals
from mxit import handles
from blend import mxm

gettext.install('blendIT');

class signals:
   def __init__(self,blend):
      self.blend = blend;

   def on_url_clicked(self,widget,href,type):
      if self.blend.autoAway:
         self.blend.autoAway.poke();

      if href.startswith("blendit://"):
         # BlendIT functions:
         # decrypt:        - Decrypt a message
         # accept          - Download a file
         # sendmessage:    - Send a message to the current tab
         # view:           - Opens a file with its default application 
         body = href.split("://")[1].replace("%3a",":");

         if body.startswith("sendmessage"):
            message = body.split(":")[1];
            n = self.blend.gui.chatWindow.notebook.get_current_page();
            jid = self.blend.gui.chatWindow.convs.getByPageNumber(n).jid;
            self.blend.mxitmessage.sendMessage(jid,message);
            return ;
         elif body.startswith("accept"):
            fileID = int(body.split(":")[1]);
            if self.blend.conn.roster._files.has_key(fileID):
               file = self.blend.conn.roster._files[fileID][0];
               # Display message to say downloading
               pN = self.blend.gui.chatWindow.notebook.get_current_page();
               conv = self.blend.gui.chatWindow.convs.getByPageNumber(pN);
               self.blend.gui.chatWindow.systemMessage(_("Downloading %s") % str(file.name),[conv],False);
               self.blend.conn.request_file(file);
               #self.blend.conn.roster._files.pop(fileID); # Prevent redownloading the file
            else:
               self.blend.gui.createErrorMessage(self.blend.gui.chatWindow,_("This file has already been downloaded."));
         elif body.startswith("decrypt"):
            # Decrypt stuff
            jid = body.split(":")[1];
            eMID = body.split(":")[2];
            # See if the eMID is still active
            conv = self.blend.gui.chatWindow.convs.getByJID(jid);
            try:
               a = conv.awaitingEncryptedMessages[eMID];
               # Create a password dialog
               dialog = decryptDialog.decryptDialog(self.blend,conv,eMID);
               dialog.run();
            except KeyError:
               # Not active anymore. Let the user know.
               self.blend.gui.createErrorMessage(self.blend.gui.chatWindow,_("This message has already been decrypted."));
         elif body.startswith("view"):
            # View stuff. Use the right starter application (depending on the OS)
            if os.name == 'mac':       # OS X
               subprocess.call(('open',body.split(":")[1]));
            elif os.name == 'nt':      # Windows
               a = body.split(":")[1:]
               path = '';
               for i in range(0,len(a)):
                  path = path + ":" + a[i];
               subprocess.call(('start',path[:-1]));
            elif os.name == 'posix':   # Linux
               subprocess.call(('xdg-open',body.split(":")[1]));
         elif body.startswith('read'):
            # View an mxm file
            if os.name == 'nt':      # Windows
               a = body.split(":")[1:]
               path = '';
               for i in range(0,len(a)):
                  path = path + ":" + a[i];
            else:
               path = body.split(":")[1];
            
            # Open file and parse
            name = os.path.splitext(os.path.split(path)[-1])[0];
            bud = handles.Buddy(path,name,'');
            self.blend.gui.chatWindow.createNewChat(bud,True,self.blend.gui.chatWindow.mxmReader);


         # -- FOLLOWING ARE FOR MXIT COMMANDS --
         elif body.startswith('sms'):
            # Unsupported
            n = self.blend.gui.chatWindow.notebook.get_current_page();
            conv = self.blend.gui.chatWindow.convs.getByPageNumber(n);
            self.blend.mxitmessage.sendCommand(conv.buddy.jid,'::type=sms|err=1:');
            self.blend.gui.chatWindow.systemMessage(_("This feature is not supported by BlendIt"),[conv]);
         elif body.startswith('platreq'):
            # Unsupported
            n = self.blend.gui.chatWindow.notebook.get_current_page();
            conv = self.blend.gui.chatWindow.convs.getByPageNumber(n);
            self.blend.mxitmessage.sendCommand(conv.buddy.jid,'::type=platreq|err=1:');
            self.blend.gui.chatWindow.systemMessage(_("This feature is not supported by BlendIt"),[conv]);
         elif body.startswith('selq'):
            # Defaults
            title = _("Select Contacts");
            message = None;
            choice = 0;
            # Get from params
            params = body.split(":")[1:];
            if params[0] != "":
               title = params[0].replace("%3a",":");
            if params[1] != "":
               message = params[1].replace("%3a",":");
            if params[2] != "":
               choice = int(params[2]);
            
            dialog = selectContactDialog.selectContactDialog(title,message,choice);
            res = dialog.run();
            if res == gtk.RESPONSE_ACCEPT:
               buddies = dialog.getSelectedContacts();
               if choice == 0:
                  data += "%s,%s;" % (buddies.jid,buddies.name); 
               else:
                  data = "";
                  for i in range(0,len(buddies)):
                     data += "%s,%s;" % (buddies[i].jid,buddies[i].name);
                  data = data[:-1];
               self.blend.mxitmessage.sendCommand(conv.buddy.jid,'::type=selq|res=%s|err=0:' % data);
            
         
      elif href.startswith(('http://','https://','mailto://','ftp://')):
         # Launch default browser with the link
         webbrowser.open_new_tab(href);

   def on_delete(self,widget,event):
      self.blend.gui.chatWindow.destroyAllChats();
      if self.blend.autoAway:
         self.blend.autoAway.poke();
      widget.hide();
      return True;

   def on_notebook_remove(self,widget,child,n):
      cW = self.blend.gui.chatWindow;
      child.destroy();
      # Check to see if we still have conversations active
      # If not, then hide the window
      if cW.convs.len == 0:
         cW.hide();
      else:
         cW.sigs.on_notebook_change(cW.notebook,'',cW.notebook.get_current_page());


   def on_notebook_change(self,widget,page,n):
      conv = self.blend.gui.chatWindow.convs.getByPageNumber(n);
      if conv is None:
         return; # Something has gone wrong!

      name = str(conv.buddy.name);

      # Change the title of the window      
      title = "%s - %s" % (name,_("Coversation"));
      self.blend.gui.chatWindow.window.set_title(title);
      gobject.timeout_add(150,self.finish_notebook_change,conv);


   def finish_notebook_change(self,conv):
      # Grab focus.. and...
      # Check to see what menu options need to be enabled/disabled
      yBuddy = (handles.BuddyType.MXIT, handles.BuddyType.JABBER);
      if conv.buddy.type in yBuddy:
         self.blend.gui.chatWindow.enableBuddyMenuOptions();
         self.blend.gui.chatWindow.loggingMenuItem.set_active(conv.logging_messages);
         self.blend.gui.chatWindow.encryptMenuItem.set_active(conv.sending_encrypted);
         if conv or conv.convEntry:
            conv.convEntry.grab_focus();
      else:
         self.blend.gui.chatWindow.disableBuddyMenuOptions();
      
      self.blend.gui.chatWindow.updateBuddyMessage();
      
      return False;

   # Save chat to gallery
   def on_save_gallery(self,widget):
      # Get the current conv
      n = self.blend.gui.chatWindow.notebook.get_current_page();
      conv = self.blend.gui.chatWindow.convs.getByPageNumber(n);
      
      if conv is not None:
         if conv.galleryMsgs is not None:
            # Send!
            self.blend.chatLogger.sendToGallery(conv);
            self.blend.gui.chatWindow.systemMessage(_("Saved to Gallery"),[conv]);
         else:
            self.blend.gui.chatWindow.systemMessage(_("No logs to send"),[conv]);

   # Launch find dialog
   def on_find(self,widget):
      window = self.blend.gui.chatWindow;
      conv = window.convs.getByPageNumber(window.notebook.get_current_page());

      if hasattr(conv,"view") == False:
         return;
      
      dialog = gtk.Dialog(_("Find"),
                          window,
                          gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                          (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                          gtk.STOCK_FIND, gtk.RESPONSE_ACCEPT)); 

      msgEntry = gtk.Entry();
      vbox = gtk.VBox();
      vbox.pack_start(gtk.Label(_("Enter the text to search for:")));
      vbox.pack_end(msgEntry,True,True);
      vbox.show_all();
      dialog.vbox.pack_start(vbox);
      
      # Wait for a response
      response = dialog.run();


      start,end = None,None;
      tag = conv.view.get_buffer().create_tag();
      col = gtk.gdk.color_parse("#F9F48F"); # Yellowish
      tag.set_property('background-gdk',col);
      tag.set_property('background-set',True);

      while response == gtk.RESPONSE_ACCEPT:
         # Search
         try:
            msg = str(msgEntry.get_text());
            
            if conv.searchingAtIter is None:
               iter = conv.view.get_buffer().get_start_iter();
            else:
               iter = conv.searchingAtIter;
               
            # clear the last iters
            if start != None:
               conv.view.get_buffer().remove_tag(tag,start,end);
            
            pair = iter.forward_search(msg,gtk.TEXT_SEARCH_VISIBLE_ONLY|gtk.TEXT_SEARCH_TEXT_ONLY);
            if pair == None:
               start,end = None,None;
               # No match found
               self.blend.gui.createErrorMessage(None,_("No match found"));
            else:
               start,end = pair; 
               conv.view.get_buffer().place_cursor(start);
               conv.view.get_buffer().apply_tag(tag,start,end);
               conv.searchingAtIter = end;

         except ImportError:
            pass; # Shouldn't get this. But better safe than sorry.

         response = dialog.run();

      # Clear the last iters.
      if start != None:
         conv.view.get_buffer().remove_tag(tag,start,end);

      conv.searchingAtIter = None;
      dialog.destroy();


   def on_view_log(self,widget):
      n = self.blend.gui.chatWindow.notebook.get_current_page();
      conv = self.blend.gui.chatWindow.convs.getByPageNumber(n);
      
      path = os.path.join('logs',str(self.blend.currentAccount.username),str(conv.buddy.jid));
      if not os.path.exists(path):
         self.blend.gui.createErrorMessage(self.blend.gui.chatWindow,
                                           _("No chat logs available"));
         return;

      if os.name == 'mac':       # OS X
         subprocess.call(('open',path));
      elif os.name == 'nt':      # Windows
         subprocess.call(('start',path));
      elif os.name == 'posix':   # Linux
         subprocess.call(('xdg-open',path));

   def on_send_file(self,widget,other=None):
      active = self.blend.gui.chatWindow.notebook.get_current_page();
      buddy = self.blend.gui.chatWindow.convs.getByPageNumber(active).buddy;
      fsigs = fileSelectionDialogSignals.signals(self.blend);
      dialog = fileSelectionDialog.fileSelectionDialog(self.blend,_("Select File"),
               fsigs.on_send_file_ok,params=buddy.jid); 
      dialog.run();

   def on_close_conv(self,widget):
      n = self.blend.gui.chatWindow.notebook.get_current_page();
      self.blend.gui.chatWindow.notebook.get_nth_page(n);
      self.blend.gui.chatWindow.destroyChat(n,True);

   def on_logging(self,widget):
      try:
         n = self.blend.gui.chatWindow.notebook.get_current_page();
      except AttributeError:
         return;

      conv = self.blend.gui.chatWindow.convs.getByPageNumber(n);
      conv.logging_messages = widget.get_active();      

   def on_encrypt(self,widget=None):
      n = self.blend.gui.chatWindow.notebook.get_current_page();
      conv = self.blend.gui.chatWindow.convs.getByPageNumber(n);
      
      if widget.get_active():
         # Popup and request a key to encrypt the message with
         eDialog = encryptDialog.encryptDialog(self.blend,conv,widget);
         eDialog.run(); 
      else:
         # Disable encryption
         conv.disableEncryption();

   def on_tab_close(self,widget,event,jid):
      # We gotta take ourself off the active chats
      n = self.blend.gui.chatWindow.convs.getPageNumberFromJID(jid);
      widget.destroy(); 
      if self.blend.gui.chatWindow.convs.getByJID(jid).private == False:        
         # We must tell everyone we're leaving...
         bud = self.blend.gui.chatWindow.convs.getByJID(jid).buddy;
         self.blend.conn.remove_buddy(bud);

      self.blend.gui.chatWindow.destroyChat(int(n));

      if self.blend.autoAway:
         self.blend.autoAway.poke();
         
      return False;


   def on_emote_btn(self,widget):
      try:
         self.blend.gui.emoteWindow.show();
      except:
         self.blend.gui.emoteWindow = emoteWindow.emoteWindow(self.blend);
         self.blend.gui.emoteWindow.show();

   def on_bold_btn(self,widget):
      self.blend.gui.chatWindow.textEntryFocus();
      if widget.get_active():
         self.blend.gui.chatWindow._bold(widget);
      else:
         self.blend.gui.chatWindow._doneformat(widget,0);

   def on_italic_btn(self,widget):
      self.blend.gui.chatWindow.textEntryFocus();
      if widget.get_active():
         self.blend.gui.chatWindow._italic(widget);
      else:
         self.blend.gui.chatWindow._doneformat(widget,1);
      
   def on_underlined_btn(self,widget):
      self.blend.gui.chatWindow.textEntryFocus();
      if widget.get_active():
         self.blend.gui.chatWindow._underline(widget);
      else:
         self.blend.gui.chatWindow._doneformat(widget,2);

   def on_highlight_btn(self,widget):
      self.blend.gui.chatWindow.textEntryFocus();
      if widget.get_active():
         self.blend.gui.chatWindow._highlight(widget);
      else:
         self.blend.gui.chatWindow._doneformat(widget,3);

   def on_bigtext_btn(self,widget):
      self.blend.gui.chatWindow.textEntryFocus();
      if widget.get_active():
         self.blend.gui.chatWindow._bigText(widget);
      else:
         self.blend.gui.chatWindow._doneformat(widget,4);

   def on_smalltext_btn(self,widget):
      self.blend.gui.chatWindow.textEntryFocus();
      if widget.get_active():
         self.blend.gui.chatWindow._smallText(widget);
      else:
         self.blend.gui.chatWindow._doneformat(widget,5);

   def on_colour_btn(self,widget):
      # Launch the colour dialog window
      if widget.get_active():
         dialog = colourSelectionDialog.colourSelectionDialog(self.blend,self.on_colour_set,widget);
         dialog.show();
      else:
         self.blend.gui.chatWindow._doneformat(widget,6);

   def on_colour_set(self,button,widget,buttonWidget,dialog):
      self.blend.gui.chatWindow.textEntryFocus();
      col = widget.get_current_color();
      self.blend.gui.chatWindow._colour(col,buttonWidget);
      dialog.destroy();

   # Catch the user pressing 'Enter' and 'Control+Enter'
   def on_key_press_event(self,widget,event,jid,buttons):
      conv = self.blend.gui.chatWindow.convs.getByJID(jid);

      # Keyboard Return and  Keypad Enter
      if event == 'return':
         # Send message
         if self.blend.currentlyConnected == False:
            return;

         # check to see if stuff needs to be closed
         self.blend.gui.chatWindow._doneallformat(buttons);
         message = self.blend.gui.chatWindow.createMarkedupMessage(conv);
         buf = conv.convEntry.get_buffer();
         #message = buf.get_text(buf.get_start_iter(),buf.get_end_iter(),True);

         n = self.blend.gui.chatWindow.notebook.get_current_page();

         # Do we append a colour to it?
         if self.blend.config.msgColour[0] == True:
            if not message.startswith("#"):
               message = "#%s" % self.blend.config.msgColour[1][1:] + message;

         # Do we send this encrypted or not?
         if conv.sending_encrypted == True:
            self.blend.mxitmessage.sendEncryptedMessage(jid,message);
         else:
            self.blend.mxitmessage.sendMessage(jid,message);
         
         # Clear the stuff after the enter goes through.
         buf.set_text("");

         return True;
      elif event == 'backspace':
         # Manage the backspacing over pixbufs and other stuff
         buf = conv.convEntry.get_buffer();
         #buf.
         
         buf.backspace(iter,True,True);
         return True;
      elif event == 'ctrl+enter':
         # Create a new line
         buf = conv.convEntry.get_buffer();
         buf.insert_at_cursor("\n");
         return True;
      elif event == 'ctrl+b':
         boldBtn = buttons.get_children()[1];
         if boldBtn.get_active():
            boldBtn.set_active(False);
         else:
            boldBtn.set_active(True);
      elif event == 'ctrl+i':
         italicBtn = buttons.get_children()[2];
         if italicBtn.get_active():
            italicBtn.set_active(False);
         else:
            italicBtn.set_active(True);
      elif event == 'ctrl+u':
         underlineBtn = buttons.get_children()[3];
         if underlineBtn.get_active():
            underlineBtn.set_active(False);
         else:
            underlineBtn.set_active(True);
      elif event == 'ctrl+h':
         highlightBtn = buttons.get_children()[4];
         if highlightBtn.get_active():
            highlightBtn.set_active(False);
         else:
            highlightBtn.set_active(True);

   def on_text_changed(self,widget):
      self.blend.gui.chatWindow._keepformat();
